package com.pai4j.zwiki.websocket.service;

import com.pai4j.common.util.JsonUtil;
import com.pai4j.zwiki.dto.ZWikiNotificationMessage;
import com.pai4j.zwiki.websocket.handler.ZWikiNotificationWebSocketHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.socket.WebSocketSession;

import java.util.HashMap;
import java.util.Map;

/**
 * ZWiki WebSocket服务
 * 
 * 提供便捷的WebSocket消息推送方法
 * 
 * 核心功能：
 * 1. 向指定用户推送通知消息
 * 2. 广播消息给所有在线用户
 * 3. 推送任务状态更新
 * 4. 推送进度更新
 * 5. 推送队列位置更新
 * 6. 查询用户在线状态
 *
 * @author pai4j
 * @since 2025-10-14
 */
@Slf4j
@Service
public class ZWikiWebSocketService {

    /**
     * 向用户推送ZWiki通知消息
     *
     * @param userId 用户ID
     * @param notification 通知消息
     * @return 是否推送成功
     */
    public boolean pushNotification(Long userId, ZWikiNotificationMessage notification) {
        if (userId == null || notification == null) {
            log.warn("推送通知参数无效. userId: {}, notification: {}", userId, notification);
            return false;
        }

        return pushNotification(String.valueOf(userId), notification);
    }

    /**
     * 向用户推送ZWiki通知消息（字符串userId）
     *
     * @param userId 用户ID（字符串）
     * @param notification 通知消息
     * @return 是否推送成功
     */
    public boolean pushNotification(String userId, ZWikiNotificationMessage notification) {
        try {
            String message = JsonUtil.toJsonString(notification);
            return ZWikiNotificationWebSocketHandler.sendToUser(userId, message);
        } catch (Exception e) {
            log.error("推送通知失败. userId: {}", userId, e);
            return false;
        }
    }

    /**
     * 向用户推送任务入队通知
     *
     * @param userId 用户ID
     * @param taskId 任务ID
     * @param queuePosition 队列位置
     * @param estimatedWaitTime 预计等待时间（分钟）
     */
    public void pushTaskQueuedNotification(Long userId, String taskId, Integer queuePosition, Integer estimatedWaitTime) {
        try {
            Map<String, Object> data = new HashMap<>();
            data.put("type", "TASK_QUEUED");
            data.put("taskId", taskId);
            data.put("queuePosition", queuePosition);
            data.put("estimatedWaitTime", estimatedWaitTime);
            data.put("message", String.format("您的任务已加入队列，当前排第%d位，预计等待%d分钟", queuePosition, estimatedWaitTime));
            data.put("timestamp", System.currentTimeMillis());

            String message = JsonUtil.toJsonString(data);
            ZWikiNotificationWebSocketHandler.sendToUser(String.valueOf(userId), message);

            log.info("推送任务入队通知. userId: {}, taskId: {}, position: {}", userId, taskId, queuePosition);

        } catch (Exception e) {
            log.error("推送任务入队通知失败. userId: {}, taskId: {}", userId, taskId, e);
        }
    }

    /**
     * 向用户推送任务开始处理通知
     *
     * @param userId 用户ID
     * @param taskId 任务ID
     * @param projectName 项目名称
     */
    public void pushTaskStartedNotification(Long userId, String taskId, String projectName) {
        try {
            Map<String, Object> data = new HashMap<>();
            data.put("type", "TASK_STARTED");
            data.put("taskId", taskId);
            data.put("projectName", projectName);
            data.put("message", "您的任务已开始处理");
            data.put("timestamp", System.currentTimeMillis());

            String message = JsonUtil.toJsonString(data);
            ZWikiNotificationWebSocketHandler.sendToUser(String.valueOf(userId), message);

            log.info("推送任务开始通知. userId: {}, taskId: {}", userId, taskId);

        } catch (Exception e) {
            log.error("推送任务开始通知失败. userId: {}, taskId: {}", userId, taskId, e);
        }
    }

    /**
     * 向用户推送任务进度更新
     *
     * @param userId 用户ID
     * @param taskId 任务ID
     * @param progress 进度（0-100）
     * @param currentStep 当前步骤描述
     */
    public void pushTaskProgressUpdate(Long userId, String taskId, Integer progress, String currentStep) {
        try {
            Map<String, Object> data = new HashMap<>();
            data.put("type", "TASK_PROGRESS");
            data.put("taskId", taskId);
            data.put("progress", progress);
            data.put("currentStep", currentStep);
            data.put("message", String.format("任务进度: %d%% - %s", progress, currentStep));
            data.put("timestamp", System.currentTimeMillis());

            String message = JsonUtil.toJsonString(data);
            ZWikiNotificationWebSocketHandler.sendToUser(String.valueOf(userId), message);

            log.debug("推送进度更新. userId: {}, taskId: {}, progress: {}%", userId, taskId, progress);

        } catch (Exception e) {
            log.error("推送进度更新失败. userId: {}, taskId: {}", userId, taskId, e);
        }
    }

    /**
     * 向用户推送任务完成通知
     *
     * @param userId 用户ID
     * @param taskId 任务ID
     * @param projectName 项目名称
     * @param resultSummary 结果摘要
     */
    public void pushTaskCompletedNotification(Long userId, String taskId, String projectName, String resultSummary) {
        try {
            Map<String, Object> data = new HashMap<>();
            data.put("type", "TASK_COMPLETED");
            data.put("taskId", taskId);
            data.put("projectName", projectName);
            data.put("message", "🎉 任务已完成！" + resultSummary);
            data.put("timestamp", System.currentTimeMillis());

            String message = JsonUtil.toJsonString(data);
            ZWikiNotificationWebSocketHandler.sendToUser(String.valueOf(userId), message);

            log.info("推送任务完成通知. userId: {}, taskId: {}", userId, taskId);

        } catch (Exception e) {
            log.error("推送任务完成通知失败. userId: {}, taskId: {}", userId, taskId, e);
        }
    }

    /**
     * 向用户推送任务失败通知
     *
     * @param userId 用户ID
     * @param taskId 任务ID
     * @param errorMessage 错误信息
     */
    public void pushTaskFailedNotification(Long userId, String taskId, String errorMessage) {
        try {
            Map<String, Object> data = new HashMap<>();
            data.put("type", "TASK_FAILED");
            data.put("taskId", taskId);
            data.put("error", errorMessage);
            data.put("message", "❌ 任务处理失败: " + errorMessage);
            data.put("timestamp", System.currentTimeMillis());

            String message = JsonUtil.toJsonString(data);
            ZWikiNotificationWebSocketHandler.sendToUser(String.valueOf(userId), message);

            log.warn("推送任务失败通知. userId: {}, taskId: {}, error: {}", userId, taskId, errorMessage);

        } catch (Exception e) {
            log.error("推送任务失败通知异常. userId: {}, taskId: {}", userId, taskId, e);
        }
    }

    /**
     * 向用户推送队列位置更新
     *
     * @param userId 用户ID
     * @param taskId 任务ID
     * @param newPosition 新位置
     */
    public void pushQueuePositionUpdate(Long userId, String taskId, Integer newPosition) {
        try {
            Map<String, Object> data = new HashMap<>();
            data.put("type", "QUEUE_POSITION_UPDATE");
            data.put("taskId", taskId);
            data.put("queuePosition", newPosition);
            data.put("message", String.format("队列位置更新: 第%d位", newPosition));
            data.put("timestamp", System.currentTimeMillis());

            String message = JsonUtil.toJsonString(data);
            ZWikiNotificationWebSocketHandler.sendToUser(String.valueOf(userId), message);

            log.debug("推送队列位置更新. userId: {}, taskId: {}, position: {}", userId, taskId, newPosition);

        } catch (Exception e) {
            log.error("推送队列位置更新失败. userId: {}, taskId: {}", userId, taskId, e);
        }
    }

    /**
     * 检查用户是否在线
     *
     * @param userId 用户ID
     * @return 是否在线
     */
    public boolean isUserOnline(Long userId) {
        if (userId == null) {
            return false;
        }
        return ZWikiNotificationWebSocketHandler.isUserOnline(String.valueOf(userId));
    }

    /**
     * 获取在线用户数
     *
     * @return 在线用户数
     */
    public int getOnlineUserCount() {
        return ZWikiNotificationWebSocketHandler.getOnlineUserCount();
    }

    /**
     * 向所有在线用户广播系统通知
     *
     * @param title 标题
     * @param message 消息内容
     */
    public void broadcastSystemNotification(String title, String message) {
        try {
            Map<String, Object> data = new HashMap<>();
            data.put("type", "SYSTEM_NOTIFICATION");
            data.put("title", title);
            data.put("message", message);
            data.put("timestamp", System.currentTimeMillis());

            String jsonMessage = JsonUtil.toJsonString(data);
            int successCount = ZWikiNotificationWebSocketHandler.broadcastToAll(jsonMessage);

            log.info("广播系统通知. title: {}, 成功推送: {}人", title, successCount);

        } catch (Exception e) {
            log.error("广播系统通知失败. title: {}", title, e);
        }
    }
}

